#ifndef oct_toolkits_h
#define oct_toolkits_h
#include <string.h>
#include <string>
#include <list>


namespace oct_tk
{


	/// 定义导出符
	/// ---------------------------------------------------------------------------------------
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32)
	/// ---------------------------------------------------------------------------------------------
	#ifndef LIB_OCT_TK_API
		#define LIB_OCT_TK_API	__declspec(dllexport)
	#else
		#define LIB_OCT_TK_API	__declspec(dllimport)
	#endif /// !lib_toolkits_api

#elif defined(_unix_) || defined(_linux_) || defined(_unix) || defined(_linux) || defined(__unix)
	/// ---------------------------------------------------------------------------------------------
	#ifndef LIB_OCT_TK_API
		#define LIB_OCT_TK_API	__attribute__((visibility ("default")))
	#endif /// !lib_toolkits_api

#endif /// !defined(_WIN32) || defined(_WIN64) || defined(WIN32)



	namespace oct_util
	{


		/// ----------------------------------------------------------------------------------------
		/// 文件操作
		enum en_file_open_mode
		{
			/// 以只读方式打开文件，只允许读取，不允许写入。该文件必须存在。
			kmode_r = 0,
			/// 	以读/写方式打开文件，允许读取和写入。该文件必须存在。
			kmode_rp = 1,
			/// 以读/写方式打开一个二进制文件，允许读/写数据。
			kmode_rbp = 2,
			/// 	以读/写方式打开一个文本文件，允许读和写。
			kmode_rtp = 3,
			/// 以只写方式打开文件，若文件存在则长度清为0，即该文件内容消失，若不存在则创建该文件。
			kmode_w = 5,
			/// 	以读/写方式打开文件，若文件存在则文件长度清为零，即该文件内容会消失。若文件不存在则建立该文件。
			kmode_wp = 6,
			/// 以追加的方式打开只写文件。若文件不存在，则会建立该文件，如果文件存在，写入的数据会被加到文件尾，即文件原先的内容会被保留（EOF符保留)。
			kmode_append = 7,
			/// 以追加方式打开可读/写的文件。若文件不存在，则会建立该文件，如果文件存在，则写入的数据会被加到文件尾后，即文件原先的内容会被保留（原来的EOF符 不保留)。
			kmode_append_p = 8,
			/// 	以只写方式打开或新建一个二进制文件，只允许写数据。
			kmode_wb = 9,
			/// 以读/写方式打开或建立一个二进制文件，允许读和写。
			kmode_wbp = 10,
			/// 以读/写方式打开或建立一个文本文件，允许读写
			kmode_wtp = 11,
			/// 以读/写方式打开一个文本文件，允许读或在文本末追加数据。
			kmode_atp = 12,
			/// 以读 / 写方式打开一个二进制文件，允许读或在文件末追加数据。
			kmode_abp = 13,

		};

		/// ----------------------------------------------------------------------------------------
		/// 年月日时分秒毫秒
		struct st_now_date_
		{
			unsigned short	year_;
			unsigned char	month_;
			unsigned char	day_;

			unsigned char	hour_;
			unsigned char	minute_;
			unsigned char	second_;
			unsigned short	mill_sec_;		/// 毫秒

			void zero_()
			{
				//memset(this, 0, sizeof(st_now_date_));
				year_ = 0;
				month_ = 0;
				day_ = 0;

				hour_ = 0;
				minute_ = 0;
				second_ = 0;
				mill_sec_ = 0;
			}

			st_now_date_()
			{
				zero_();
			}
		};
		typedef st_now_date_ st_now_date;

		/// ----------------------------------------------------------------------------------------
		enum
		{
			/// 日志文件大小: 5M
			klog_file_size = 5 * 1024 * 1024,
		};

		struct st_log_info_
		{
			/// 日志文件存在路径, 例如: c:/logs/demo, 也支持： c:\\logs\\demo
			std::string			path_;
			/// 日志文件名前缀	例如： C_2021_03_27中，前缀就是 C
			std::string			prefix_;
			/// 日志文件名后缀	例如： 2021_03_27_C 中， 后缀就是 C
			std::string			postfix_;
			/// 日志文件格式	例如： C_2021_03_27.log中， ".log"就是文件格式 )
			std::string			type_;
			/// 日志文件大小	,	默认大小为 5M 
			unsigned int		size_;
			/// 保存文件的打开方式, 见【en_file_open_mode】的定义，默认: kmode_w
			unsigned int		file_open_mode_;

			void zero_()
			{
				path_.clear();
				prefix_.clear();
				postfix_.clear();
				type_.clear();
				size_ = klog_file_size;
				file_open_mode_ = kmode_w;
			}


			st_log_info_()
			{
				zero_();
			}
		};

		typedef st_log_info_	st_log_info;



		/// ----------------------------------------------------------------------------------------
		/// 文件读写接口
		/// ----------------------------------------------------------------------------------------
		class iFile
		{
		public:

			///  --------------------------------------------------------------------------------
			///  @brief:	初始化
			///  @str_file - 文件所在绝对路径， 例如： C:/demo/logs/1.txt
			///  @open_mode - 以哪种方式打开文件
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败, 参数【str_file】字符串为空
			///				2 - 失败，参数【open_mode】不是给定的枚举范围
			///				3 - 失败，文件打开失败。
			///  --------------------------------------------------------------------------------
			virtual int init_(const std::string& str_file, const oct_tk::oct_util::en_file_open_mode open_mode) = 0;


			///  --------------------------------------------------------------------------------
			///  	返回当前初始化的文件
			///  @return - std::string	
			/// 			
			///  --------------------------------------------------------------------------------
			virtual std::string file_() = 0;


			///  --------------------------------------------------------------------------------
			///  	文件是否打开
			///  @return - bool	
			/// 			true - 打开
			///				false - 没有打开
			///  --------------------------------------------------------------------------------
			virtual bool is_opened_() = 0;


			///  --------------------------------------------------------------------------------
			///  	返回文件长度,单位： 字节
			///  @return - int	
			/// 			返回值X， 
			///				-2 - 失败，请先执行初始化
			///				X >=0 , 文件长度，单位：字节
			///  --------------------------------------------------------------------------------
			virtual int length_() = 0;


			///  --------------------------------------------------------------------------------
			///  	写文件, 将数据写入
			///  @pbuf - 待写入内容
			///  @pbuf_len - 待写入数据长度
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败，请先初始化
			///				2 - 失败，参数【pbuf】为nullptr或者NULL
			///				3 - 失败，写文件失败
			///  --------------------------------------------------------------------------------
			virtual int write_(const char* pbuf, unsigned int pbuf_len) = 0;
			///  --------------------------------------------------------------------------------
			///  	写文件
			///  @str_write - 待文件内容
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败，请先初始化
			///				2 - 失败，参数【str_write】的长度为0
			///				3 - 失败，写文件失败
			///  --------------------------------------------------------------------------------
			virtual int write_(const std::string& str_write) = 0;

			///  --------------------------------------------------------------------------------
			///  	将文件内容儒道参数【str_read】中
			///  @str_read - 返回文件内容
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败，请先初始化
			///				2 - 失败，读取文件缓冲创建失败
			///				3 - 失败，读取文件失败
			///  --------------------------------------------------------------------------------
			virtual int read_(std::string& str_read) = 0;

			///  --------------------------------------------------------------------------------
			///   读文件内容， 参数【pout_buf】需要外部申请，函数内不会维护，读取成功后，文件内容存放在pout_buf中。
			///  @pout_buf - 返回读取文件内容
			///  @pout_buf_len - 【pout_buf】缓冲区的长度
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败，请先初始化
			///				2 - 失败，参数【pout_buf】为空 或者 参数【pout_buf_len】的值是0
			///  --------------------------------------------------------------------------------
			virtual int read_(char* pout_buf, unsigned int pout_buf_len) = 0;

			///  --------------------------------------------------------------------------------
			///  	判断参数【str_check_file】的文件是否存在
			///  @str_check_file - 
			///  @return - bool	
			/// 			
			///  --------------------------------------------------------------------------------
			virtual bool is_existed_(const std::string& str_check_file) = 0;

			///  --------------------------------------------------------------------------------
			///  	避免析构时出现异常，请销毁前先调用该函数完成内部资源释放
			///  @return - int	
			/// 			0 - 成功
			///  --------------------------------------------------------------------------------
			virtual int uninit_() = 0;
		};



		/// ----------------------------------------------------------------------------------------
		/// 导出函数
#ifdef __cplusplus
		extern "C" {
#endif/// 

			///  --------------------------------------------------------------------------------
			///  	创建文件读写对象
			///  @return - lib_toolkits_api ifile*	
			/// 			返回模块对象，如果创建失败，则返回NULL
			///  --------------------------------------------------------------------------------
			LIB_OCT_TK_API iFile* new_ifile_();

			///  --------------------------------------------------------------------------------
			///  	释放文件模块, 释放后，函数内部将其置为NULL，
			///  @pobj - 来自函数【create_ifile_】创建的结果
			///  @return - lib_toolkits_api ifile*	
			/// 		
			///  --------------------------------------------------------------------------------
			LIB_OCT_TK_API iFile* del_ifile_(iFile* pobj);


#ifdef __cplusplus
		}
#endif/// 





		/// ----------------------------------------------------------------------------------------
		/// 日志文件接口类
		/// ----------------------------------------------------------------------------------------
		class iLog
		{
		public:
			///  --------------------------------------------------------------------------------
			///  	初始化， 
			///  @info - 日志信息
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败，日志文件路径不正确
			///				2 - 失败，如果磁盘空间剩余不够，则禁止创建日志文件对象
			///				3 - 失败，无法创建日志文件路径， 无法写入日志
			///				5 - 失败，创建日志文件失败，则无法写入日志
			///  --------------------------------------------------------------------------------
			virtual int init_(const oct_util::st_log_info& info) = 0;

			/// ----------------------------------------------------------------------------
			/// @brief：		将参数中的数据按照 init_ 中打开方式写入
			/// @param: 	const char * pdata - pdata
			/// @param: 	const unsigned int length - length
			/// @return: 	int 
			/// 			0 - 成功
			///				1 - 失败，磁盘控件不足以写入length的数据
			///				2 - 失败，文件写入对象创建失败
			/// ----------------------------------------------------------------------------
			virtual int log_by_opening_type_(const char* pdata, const unsigned int length) = 0;

			///  --------------------------------------------------------------------------------
			///  写日志，日志内容为文本，且每一行前面都带有时间； 例如： [2021-03-28 15:00:00:001] 日志文件内容
			///  @str_log - 待写入日志文件内容
			///  @return - int	
			/// 			0 - 成功
			///				1 - 无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
			///				2 - 失败，无法创建写日志文件对象，请先初始化
			///  --------------------------------------------------------------------------------
			virtual int log_text_(const std::string& str_log) = 0;

			///  --------------------------------------------------------------------------------
			///  	写日志
			///  @pdata - 待写入内容
			///  @pdata_len - 待写入长度
			///  @return - int	
			/// 			0 - 成功、
			///				1 - 失败，参数【pdata】为空或者参数【pdata_len】为0
			///				2 - 失败，无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
			///				3 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
			///  --------------------------------------------------------------------------------
			virtual int log_text_(const char* pdata, unsigned int pdata_len) = 0;

			///  --------------------------------------------------------------------------------
			///  	将参数【str_log】每个字节的16进制写入文件，全部大写
			///  @str_log - 待写入内容
			///  @return - int	
			///				0 - 成功
			/// 			1 - 无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
			///				2 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
			///  --------------------------------------------------------------------------------
			virtual int log_hex_(const std::string& str_log) = 0;

			///  --------------------------------------------------------------------------------
			///  	将参数【pdata】每个字节的16进制写入文件，全部大写
			///  @pdata - 待写入内容
			///  @pdata_len - 写入内容长度
			///  @return - int	
			/// 			0 - 成功
			///				1 - 失败，参数【pdata】为空或者参数【pdata_len】为0
			///				2 - 失败，无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
			///				3 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
			///  --------------------------------------------------------------------------------
			virtual int log_hex_(const char* pdata, unsigned int pdata_len) = 0;


			///  --------------------------------------------------------------------------------
			///  	释放内部资源
			///  @return - void	
			/// 			
			///  --------------------------------------------------------------------------------
			virtual void uninit_() = 0;
		};



		/// ----------------------------------------------------------------------------------------
		/// 导出函数
#ifdef __cplusplus
		extern "C" {
#endif/// 

			///  --------------------------------------------------------------------------------
			///  	创建日志文件读写对象
			///  @return - lib_toolkits_api ilog*	
			/// 			返回模块对象，如果创建失败，则返回NULL
			///  --------------------------------------------------------------------------------
			LIB_OCT_TK_API iLog* create_ilog_();

			///  --------------------------------------------------------------------------------
			///  	释放文件模块, 释放后，函数内部将其置为NULL，
			///  @pobj - 来自函数【create_ilog_】创建的结果
			///  @return - lib_toolkits_api ilog*	
			/// 		
			///  --------------------------------------------------------------------------------
			LIB_OCT_TK_API iLog* release_ilog_(iLog* pobj);


#ifdef __cplusplus
		}
#endif/// 





		/// ----------------------------------------------------------------------------------------
		/// 常用工具
		/// ----------------------------------------------------------------------------------------
		class LIB_OCT_TK_API toolkits
		{
		public:
			explicit toolkits();
			virtual ~toolkits();

			///  --------------------------------------------------------------------------------
			///  	返回年月日时分秒毫秒字符串
			///  @return - std::string	
			/// 			
			///  --------------------------------------------------------------------------------
			st_now_date get_date_now_();

			///  --------------------------------------------------------------------------------
			///  	格式化字符串
			///  @pformat - 格式化字符串
			///  @ - 参数列表
			///  @return - std::string	
			/// 			返回格式化结果
			///  --------------------------------------------------------------------------------
			std::string str_format_(const char*pformat, ...);


			///  --------------------------------------------------------------------------------
			///  	获取可执行程序所在绝对路径
			///  @return - std::string	
			/// 			
			///  --------------------------------------------------------------------------------
			std::string get_executable_dir_();


			/// -----------------------------------------------------------------
			/// windows特有的转码函数, 如果是非Windows平台调用，则返回空的字符串
			/// -----------------------------------------------------------------

			///  --------------------------------------------------------------------------------
			///  @brief: 	utf8字符串转ascii
			///  @param:	const std::string & str_utf8 - utf8字符串编码 
			///  @return:	std::string	
			/// 			ascii字符串编码
			///  --------------------------------------------------------------------------------
			std::string utf8_to_ascii_(const std::string& str_utf8);


			///  --------------------------------------------------------------------------------
			///  @brief: 	ascii字符编码转utf8字符串
			///  @param:	const std::string & str_acsii - acsii编码字符串
			///  @return:	std::string	
			/// 			utf8字符串
			///  --------------------------------------------------------------------------------
			std::string acsii_to_utf8_(const std::string& str_acsii);

		private:
			/// 屏蔽拷贝构造函数
			toolkits(const toolkits& instance) {}
			toolkits& operator =(const toolkits& instance) { return *this; }
		};

	}	/// end namespace oct_util



	namespace oct_commu
	{


		/// ----------------------------------------------------------------------------
		/// @brief: 数据处理接口类
		/// ----------------------------------------------------------------------------
		class IDataHandle
		{
		public:
			virtual ~IDataHandle() {}

		public:
			/// ----------------------------------------------------------------------------
			/// @brief：		接收数据处理
			/// @param: 	const unsigned char * pdata - 收到数据
			/// @param: 	const unsigned int len - 收到数据长度
			/// @return: 	int - 无
			/// 			
			/// ----------------------------------------------------------------------------
			virtual int recv_data_(const unsigned char* pdata, const unsigned int len) = 0;


			/// ----------------------------------------------------------------------------
			/// @brief：		发送数据
			/// @param: 	const unsigned char * pdata - 待发送数据
			/// @param: 	const unsigned int len - 待发送数据长度
			/// @return: 	int - 无
			/// 			0 - 成功
			///				1 - 失败，pdata 为空或者 len 为 0
			/// ----------------------------------------------------------------------------
			virtual int send_data_(const unsigned char* pdata, const unsigned int len) = 0;
		};





		/// ----------------------------------------------------------------------------
		/// @brief: UDP
		/// ----------------------------------------------------------------------------

		/// ----------------------------------------------------------------------------
		/// @brief: 组播类型
		/// ----------------------------------------------------------------------------
		enum en_cast_type
		{
			CT_NONE = 0,
			/// 单播
			CT_UNI = 1,
			/// 组播
			CT_MULTI = 2,
			/// 广播
			CT_BROAD = 3,
		};

		/// ----------------------------------------------------------------------------
		/// @brief: IP类型
		/// ----------------------------------------------------------------------------
		enum en_ip_ver
		{
			IP_V6 = 2,
			IP_V4 = 1,

		};

		/// ----------------------------------------------------------------------------
		/// @brief: socket版本
		/// ----------------------------------------------------------------------------
		enum en_socket_ver
		{
			SOCK_VER_4 = 1,
			SOCK_VER_6 = 2,
		};


		/// ----------------------------------------------------------------------------
		/// @brief: IP配置
		/// ----------------------------------------------------------------------------
		struct st_ip_config_
		{
			/// IP值
			std::string value_;
			/// IP 版本
			int ver_;

			void zero_()
			{
				value_.clear();
				ver_ = IP_V4;
			}
			st_ip_config_()
			{
				zero_();
			}

		};

		typedef st_ip_config_ ip_config;


		/// ----------------------------------------------------------------------------
		/// @brief: UDP初始化参数
		/// ----------------------------------------------------------------------------
		struct stUDPInit_
		{
			/// 组播类型
			int		cast_type_;
			/// 本机IP
			std::string local_ip_;
			/// 目标IP
			std::string target_ip_;
			/// 目标端口
			unsigned int target_port_;
			/// socket版本
			int socket_ver_;

			void zero_()
			{
				/// 默认单播
				cast_type_ = CT_UNI;
				local_ip_ = std::string("127.0.0.1");
				target_ip_ = std::string("127.0.0.1");
				target_port_ = 27500;
				socket_ver_ = SOCK_VER_4;
			}

			stUDPInit_()
			{
				zero_();
			}
		};


		typedef stUDPInit_ stUDPInit;

		/// ----------------------------------------------------------------------------
		/// @brief: udp通信接口类
		/// ----------------------------------------------------------------------------
		class IUDP
		{
		public:
			virtual ~IUDP() {}
			/// ----------------------------------------------------------------------------
			/// @brief：		初始化
			/// @param: 	const udp_init_params & param - param
			/// @param: 	idata_handle * pdata_handle - 接收数据， 如果不需要，则传 nullptr
			/// @return: 	int - 无
			/// 			
			/// ----------------------------------------------------------------------------
			virtual int init_(const stUDPInit& param, IDataHandle* precv_data) = 0;

			/// ----------------------------------------------------------------------------
			/// @brief：		send_
			/// @param: 	const unsigned char * pdata - pdata
			/// @param: 	const unsigned int len - len
			/// @return: 	int - 无
			/// 			
			/// ----------------------------------------------------------------------------
			virtual int send_(const unsigned char* pdata, const unsigned int len) = 0;

			/// ----------------------------------------------------------------------------
			/// @brief：		退出前调用
			/// @return: 	int - 无
			/// 			
			/// ----------------------------------------------------------------------------
			virtual int uninit_() = 0;
		};



#ifdef __cplusplus
		extern "C" {
#endif/// 

			/// ----------------------------------------------------------------------------
			/// @brief：		创建，失败，则返回nullptr
			/// @return: 	lib_export iudp* - 无
			/// 			
			/// ----------------------------------------------------------------------------
			LIB_OCT_TK_API IUDP* new_udp_();


			/// ----------------------------------------------------------------------------
			/// @brief：		释放， 内部设置为nullptr再返回
			/// @param: 	iudp * pobj - pobj
			/// @return: 	lib_export iudp* - 无
			/// 			
			/// ----------------------------------------------------------------------------
			LIB_OCT_TK_API IUDP* del_udp_(IUDP* pobj);






			/// ----------------------------------------------------------------------------
			/// @brief: 网络适配器
			/// ----------------------------------------------------------------------------
			class LIB_OCT_TK_API CommuUtil
			{
			public:
				explicit CommuUtil();
				virtual ~CommuUtil();

				/// ----------------------------------------------------------------------------
				/// @brief：		格式化字符串
				/// @param: 	const char * pformat - pformat
				/// @param: 	... - 
				/// @return: 	std::string - 无
				/// 			
				/// ----------------------------------------------------------------------------
				std::string str_format_(const char*pformat, ...);

				/// ----------------------------------------------------------------------------
				/// @brief：		读取本机所有IPv4
				/// @param: 	std::list<std::string> & out_list - out_list
				/// @return: 	int - 无
				/// 			0 - 读取成功
				///				
				/// ----------------------------------------------------------------------------
				int ipv4_(std::list<std::string>& out_list);

				/// ----------------------------------------------------------------------------
				/// @brief：		读取本机IPv6
				/// @param: 	std::list<std::string> & out_list - out_list
				/// @return: 	int - 无
				/// 			0 - 读取成功
				/// ----------------------------------------------------------------------------
				int ipv6_(std::list<std::string>& out_list);


			};

#ifdef __cplusplus
		}
#endif/// 

	}

}

#endif /// oct_toolkits_h